3.3.6 使用其他多路复用器

因为创建一个处理器和多路复用器唯一需要做的就是实现 ServeHTTP 方法,所以通过自行创建多路复用器来代替 net/http 包中的 ServeMux 是完全可行的,并且目前市面上已经出现了很多第三方的多路复用器可供使用,比如,Gorilla Toolkit就是一个非常优秀的第三方多路复用器包,它提供了 muxpat 这两个工作方式非常不同的多路复用器,而本节将要介绍的则是另一个高效的轻量级第三方多路复用器——HttpRouter。

ServeMux 的一个缺陷是无法使用变量实现URL模式匹配。虽然在浏览器请求 /threads 的时候,使用 ServeMux 可以很好地获取并显示论坛中的所有帖子,但如果浏览器请求的是 /thread/123 ,那么要获取并显示论坛里面ID为123的帖子就会变得非常困难。程序必须对URL进行语法分析才能提取出URL当中的帖子ID。此外,因为受 ServeMux 实现URL模式匹配的方式所限,如果我们想要通过 /thread/123/post/456 这样的URL从ID为123的帖子中获取ID为456的回复,就必须在程序里面进行大量复杂的语法分析,并因此给程序带来额外的复杂度。

ServeMux 不同, HttpRouter 包并没有上面提到的这些限制。本节将对 HttpRouter 包最重要的一部分特性进行介绍,关于这个包的更详细的说明可以在它的文档页面里面看到:https://github.com/julienschmidt/httprouter。代码清单3-12展示了一个使用HttpRouter实现的服务器。

代码清单3-12 使用HttpRouter实现的服务器

package main
import (
  "fmt"
  "github.com/julienschmidt/httprouter"
  "net/http"
)
func hello(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
  fmt.Fprintf(w, "hello, %s!\n", p.ByName("name"))
}
func main() {
  mux := httprouter.New()
  mux.GET("/hello/:name", hello)
  server := http.Server{
    Addr: "127.0.0.1:8080",
    Handler: mux,
  }
  server.ListenAndServe()
}

这个程序中的大部分代码都和之前展示过的代码一样,只是涉及多路复用器的部分代码跟之前有所不同。在这段代码里,程序通过调用 New 函数来创建一个多路复用器:

mux := httprouter.New()

这个程序不再使用 HandleFunc 绑定处理器函数,而是直接把处理器函数与给定的HTTP方法进行绑定:

mux.GET("/hello/:name", hello)

这段代码会把给定URL的 GET 方法与 hello 处理器函数进行绑定,当浏览器向这个URL发送 GET 请求时, hello 函数就会被调用,但如果浏览器向这个URL发送除 GET 请求之外的其他请求, hello 函数则不会被调用。需要注意的是,被绑定的URL包含了具名参数(named parameter),这些具名参数会被URL中的具体值所代替,并且程序可以在处理器里面获取这些值。

跟之前的处理器函数相比,现在的 hello 处理器函数也发生了变化,它不再接受两个参数,而是接受3个参数。其中第三个参数 Params 就包含了之前提到的具名参数,具名参数的值可以在处理器内部通过 ByName 方法获取:

func hello(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
   fmt.Fprintf(w, "hello, %s!\n", p.ByName("name"))
}

程序的最后一个变化是它不再使用默认的 DefaultServeMux ,而是通过将HttpRouter传递给 Server 结构来使用这个多路复用器:

server := http.Server{
 Addr: "127.0.0.1:8080",
 Handler: mux,
}
server.ListenAndServe()

现在,如果我们在终端上执行 go build 命令,那么编译器将返回一个错误:

$ go build
server.go:5:5: cannot find package "github.com/julienschmidt/httprouter" in
 any of:
  /usr/local/go/src/github.com/julienschmidt/httprouter (from $GOROOT)
  /Users/sausheong/gws/src/github.com/julienschmidt/httprouter (from $GOPATH)

出现这个错误的原因在于,我们虽然指定了HttpRouter库,但这个第三方库在我们的电脑上并不存在,得益于Go语言强大且易用的包管理系统,我们只需要执行以下命令就可以解决这个问题了:

$ go get github.com/julienschmidt/httprouter

在计算机连接了网络的情况下,这个命令会从HttpRouter的GitHub主页上下载HttpRouter包的源代码,并将其存储到 $GOPATH/src 目录中。在此之后,当我们再次执行 go build 命令尝试编译代码清单3-12所示的服务器时,编译器就会导入HttpRouter的代码,并对整个服务器进行编译。

results matching ""

    No results matching ""